package com.wxapp.common.core.filter;

import com.wxapp.common.constant.enums.ResultEnum;
import com.wxapp.common.constant.pojo.vm.ResponseVm;
import com.wxapp.common.constant.pojo.vm.ResultVm;
import com.wxapp.common.core.filter.except.LoginException;
import com.wxapp.common.core.filter.except.MqException;
import com.wxapp.common.core.filter.except.ThrowMyException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.stream.Collectors;

@ControllerAdvice
public class ExceptionFilter extends ResponseVm {
    private static final Logger log = LoggerFactory.getLogger(ExceptionFilter.class);

    /**
     * 登录异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = LoginException.class)
    @ResponseBody
    public ResultVm<String> exceptionHandler(LoginException e) {
        log.error("=====出现异常======\n\r", e);
        return define(e.getCode(), e.getMessage(), null);
    }

    /**
     * 处理空指针的异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    @ResponseBody
    public ResultVm<String> exceptionHandler(HttpServletRequest req, NullPointerException e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.UNPROCESSABLE_ENTITY, e.getMessage(), null);
    }

    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultVm<String> exceptionHandler(HttpServletRequest req, Exception e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.INTERNAL_SERVER_ERROR, e.getMessage(), null);
    }

    /**
     * 处理请求参数格式错误 @RequestBody上使用@Valid 实体上使用@NotNull等，验证失败后抛出的异常是MethodArgumentNotValidException异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultVm<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        log.error("=====出现异常======\n\r", e);
        String message = e.getBindingResult().getAllErrors().stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining());
        return ResponseVm.define(ResultEnum.UNPROCESSABLE_ENTITY, message, null);
    }

    /**
     * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultVm<String> BindExceptionHandler(BindException e) {
        log.error("=====出现异常======\n\r", e);
        String message = e.getBindingResult().getAllErrors().stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining());
        return ResponseVm.define(ResultEnum.UNPROCESSABLE_ENTITY, message, null);
    }

    /**
     * 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultVm<String> ConstraintViolationExceptionHandler(ConstraintViolationException e) {
        log.error("=====出现异常======\n\r", e);
        String message = e.getConstraintViolations().stream().map(s -> s.getMessage()).collect(Collectors.joining());
        return ResponseVm.define(ResultEnum.UNPROCESSABLE_ENTITY, message, null);
    }

    /**
     * 参数格式异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public ResultVm<String> HttpMessageNotReadableExceptionHandler(HttpMessageNotReadableException e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.UNPROCESSABLE_ENTITY, e.getMessage(), null);
    }

    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public ResultVm<String> runtimeException(HttpServletRequest req, Exception e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.INTERNAL_SERVER_ERROR, e.getMessage(), null);
    }

    /**
     * 抛出自定义异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = ThrowMyException.class)
    @ResponseBody
    public ResultVm<String> ThrowMyException(HttpServletRequest req, Exception e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.INTERNAL_SERVER_ERROR, e.getMessage(), null);
    }

    /**
     * 自定义中间件错误
     */
    @ExceptionHandler(value = MqException.class)
    @ResponseBody
    public ResultVm<String> ThrowMqException(HttpServletRequest req, Exception e) {
        log.error("=====出现异常======\n\r", e);
        return ResponseVm.define(ResultEnum.MQ_ERROR, e.getMessage(), null);
    }
}
